package org.gikolet.ch2.android.widget;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.gikolet.ch2.data.Res;
import org.gikolet.ch2.data.ThreadHeader;
import org.gikolet.ch2.logic.ResesLogic;

import roboguice.inject.ContextScoped;
import android.content.Context;
import android.text.Layout;
import android.text.Spannable;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.Layout.Alignment;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;

import com.google.inject.Inject;
import com.google.inject.name.Named;

@ContextScoped
public class ResListView extends ListView {

	private final LayoutInflater inflater;

	public static final String RES_LIST_VIEW_LAYOUT_ID = "resListViewLayout";
	public static final String RES_LIST_VIEW_ID = "resListViewId";

	@Inject
	@Named(RES_LIST_VIEW_LAYOUT_ID)
	private int layout;

	@Inject
	@Named(RES_LIST_VIEW_ID)
	private int resId;

	private ThreadHeader threadHeader;

	private List<Spannable> resCache = new ArrayList<Spannable>();

	@Inject
	private ResesLogic resesLogic;

	private ResAdapter innerAdapter;

	private ResSpannableParser resSpannableParser;

	private int beforePosition = -1;

	private boolean first = true;

	class ViewHolder {
		FastTextView resTextView;
	}

	@Inject
	public ResListView(Context context) {
		super(context);

		this.inflater = (LayoutInflater) context
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

		this.resSpannableParser = new ResSpannableParser();

		this.innerAdapter = new ResAdapter();
		super.setAdapter(this.innerAdapter);

		setItemsCanFocus(true);
		setFastScrollEnabled(false);

		setOnItemSelectedListener(new OnItemSelectedListener() {
			public void onItemSelected(AdapterView<?> parent, View view,
					int position, long id) {
				ResListView.this.onItemSelected(view, position, id);
			}

			public void onNothingSelected(android.widget.AdapterView<?> parent) {
			};
		});

		this.resSpannableParser.setOnResClickListener(new OnResClickListener() {
			public void onResNoClick(int resNo) {
				ResListView.this.onResNoClick(resNo);
			}

			public void onResAnchorClick(int resNoStart, int resNoEnd) {
				ResListView.this.onResAnchorClick(resNoStart, resNoEnd);
			}
		});
	}

	public void onResNoClick(int resNo) {
		System.out.println("no:" + resNo);
	}

	public void onResAnchorClick(int resNoStart, int resNoEnd) {
		setSelection(resNoStart - 1);
	}

	private void onItemSelected(View view, int position, long id) {
		if (this.first) {
			dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
					KeyEvent.KEYCODE_DPAD_DOWN));

			this.first = false;

		} else {
			if (position != -1) {
				if (this.beforePosition < position) {
					view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
							KeyEvent.KEYCODE_DPAD_DOWN));

				} else if (this.beforePosition > position) {
					view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
							KeyEvent.KEYCODE_DPAD_UP));
				}
			}
		}
		this.beforePosition = position;
	}

	private List<Spannable> getResCache() {
		if (this.threadHeader == null) {

			if (this.resCache.isEmpty()) {
				for (int i = 0; i < 100; i++) {
					Res r = new Res();

					r.setName("名無しさん");
					String body = "";
					body += ">>>0０1-3,０4-０05,6-,7\n";
					// body += "てすと06\n";
					// body += "てすと07\n";
					// body += "てすと08\n";
					// body += "てすと09\n";
					// body += "てすと10\n";
					// body += "てすと11\n";
					// body += "てすと12\n";
					// body += "てすと13\n";
					// body += "てすと14\n";
					// body += "てすと15\n";
					// body += "てすと16\n";
					// body += "てすと17\n";
					// body += "てすと18\n";
					// body += "てすと19\n";
					// body += "てすと10\n";
					// body += "てすと21\n";
					// body += "てすと22\n";
					// body += "てすと23\n";
					// body += "てすと24\n";
					// body += "てすと25\n";
					// body += "てすと26\n";
					// body += "てすと27\n";
					// body += "てすと28\n";
					// body += "てすと29\n";
					// body += "てすと30\n";
					// body += "てすと31\n";
					// body += "てすと32\n";
					// body += "てすと33\n";
					// body += "てすと34\n";
					// body += "てすと35\n";
					// body += "てすと36\n";
					// body += "てすと37\n";
					// body += "てすと38\n";
					// body += "てすと39\n";
					// body += "てすと40\n";
					// body += "てすと41\n";
					// body += "てすと42\n";
					// body += "てすと43\n";
					// body += "てすと44\n";
					// body += "てすと45\n";
					// body += "てすと46\n";
					// body += "てすと47\n";
					// body += "てすと48\n";
					// body += "てすと49\n";
					// body += "てすと50\n";
					// body += "てすと51\n";
					// body += "てすと52\n";
					// body += "てすと53\n";
					// body += "てすと54\n";
					// body += "てすと55\n";
					// body += "てすと56\n";
					// body += "てすと57\n";
					// body += "てすと58\n";
					// body += "てすと59\n";
					// body += "てすと60\n";
					// body += "てすと61\n";
					// body += "てすと62\n";
					body += "http://gikolet.org/\n";
					body += "http://www.ch2.net/\n";
					body += "http://www.ch2.net/\n";
					body += "http://www.ch2.net/\n";
					body += "http://www.ch2.net/";

					r.setBody(body);
					r.setMail("sage");
					r.setDateString("2009/01/01");

					this.resCache.add(this.resSpannableParser.toSpannable(
							i + 1, r));
				}
			}

		} else if (this.resCache.isEmpty()) {
			try {
				List<Res> reses = this.resesLogic.getReses(this.threadHeader);
				for (int i = 0; i < reses.size(); i++) {
					this.resCache.add(this.resSpannableParser.toSpannable(
							i + 1, reses.get(i)));
				}

			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return this.resCache;
	}

	private int getAdCount() {
		return getResCache().size();
	}

	public Spannable getAdItem(int position) {
		return getResCache().get(position);
	}

	public long getAdItemId(int position) {
		return position;
	}

	public void setThreadHeader(ThreadHeader threadHeader) {
		this.threadHeader = (threadHeader != null) ? new ThreadHeader(
				threadHeader) : null;

		this.resCache.clear();
		this.innerAdapter.notifyDataSetChanged();
	}

	public ThreadHeader getThreadHeader() {
		return new ThreadHeader(this.threadHeader);
	}

	private CacheLayoutProvider cacheLayoutProvider = new CacheLayoutProvider();

	public View getAdView(int i, View convertView, ViewGroup viewgroup) {
		ViewHolder holder;

		if (convertView == null) {
			convertView = this.inflater.inflate(this.layout, viewgroup, false);

			holder = new ViewHolder();
			holder.resTextView = (FastTextView) convertView
					.findViewById(this.resId);

			holder.resTextView.setFocusable(true);
			holder.resTextView.setClickable(true);
			holder.resTextView.setLongClickable(true);

			holder.resTextView.setLayoutProvider(cacheLayoutProvider);

			convertView.setTag(holder);

		} else {
			holder = (ViewHolder) convertView.getTag();
		}

		FastTextView resView = holder.resTextView;

		resView.setText(getAdItem(i));

		return convertView;
	}

	class ResAdapter extends BaseAdapter {

		public int getCount() {
			return getAdCount();
		}

		public Spannable getItem(int position) {
			return getAdItem(position);
		}

		public long getItemId(int position) {
			return getAdItemId(position);
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			return getAdView(position, convertView, parent);
		}
	}

	class CacheLayoutProvider implements LayoutProvider {

		private Map<CharSequence, Layout> layoutMap = new HashMap<CharSequence, Layout>();

		private int oldWidth = -2;

		public CacheLayoutProvider() {
		}

		public Layout getLayout(CharSequence text, int width,
				TextPaint textPaint) {

			Layout layout = this.layoutMap.get(text);

			if (width != this.oldWidth) {
				layout = null;
				this.oldWidth = width;
			}

			if (layout == null) {
				layout = new StaticLayout(text, textPaint, width,
						Alignment.ALIGN_NORMAL, 1, 0, true);

				this.layoutMap.put(text, layout);
			}

			return layout;
		}
	}
}
